%%%-----------------------------------------------------------------------------
%%% @doc
%%% emqttd for ios apns.
%%%
%%% @end
%%%-----------------------------------------------------------------------------
-module (emqttd_apns).

-behaviour(gen_server).

-define(SERVER, ?MODULE).

%% API Exports 
-export([start_link/2, pool/0, send_apns_message/6]).

%% gen_server Function Exports
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
         terminate/2, code_change/3]).

-record(state, {id, apn_server}).

-define(APNS_POOL, apns_pool).

%%%=============================================================================
%%% API
%%%=============================================================================

%%------------------------------------------------------------------------------
%% @doc Start Ack manager
%% @end
%%------------------------------------------------------------------------------
start_link(Id, Apns) ->
    gen_server:start_link(?MODULE, [Id, Apns], []).

pool()  -> ?APNS_POOL.

message_id() ->
  {_, _, MicroSecs} = os:timestamp(),
  Secs = calendar:datetime_to_gregorian_seconds(calendar:universal_time()),
  First = Secs rem 65536,
  Last = MicroSecs rem 65536,
  <<First:2/unsigned-integer-unit:8, Last:2/unsigned-integer-unit:8>>.

-record(apns_msg, {id = message_id()            :: binary(),
                   expiry = apns:expiry(86400)  :: non_neg_integer(), %% default = 1 day
                   device_token                 :: string(),
                   content_available = false    :: boolean(),
                   alert = none                 :: none | apns:alert(),
                   badge = none                 :: none | integer(),
                   category = none              :: none | string(),
                   sound = none                 :: none | apns:apns_str(),
                   apns_extra = []              :: none | [{atom(), integer()|boolean()|string()}],
                   extra = []                   :: proplists:proplist(),
                   priority = 10                :: integer()}).


send_apns_message( Username, Appkey, Token, _Message, Count, Extra) ->
    ShowMsg = 
    case proplists:get_value( <<"title">>, Extra, undefined ) of
        undefined ->
            MsgTmp = unicode:characters_to_binary( ":给你发了一条消息" ),
            util:print("~p ~p ~n",[ Username, MsgTmp ]),
            << Username/binary, MsgTmp/binary>>;
        Title ->
            Title
    end,
        
    Node = util:get_value_cache( emqttd, ham_server, 'ham_server@127.0.0.1'),
    ApnsMsg = #apns_msg{
      alert  = util:a2b( ShowMsg ),
      badge  = Count,
      sound  = "sound" ,
      category = "EMAIL_ACTION",
      expiry = 1348000749,
      device_token = Token,
      extra = Extra
    },
    case Appkey of
        <<"owner">> ->
            util:print("[ owner_apns send_msg ]: ShowMsg:~ts Count:~p ~n", [ShowMsg, Count]),
            cast_svc:cast(Node, apns, send_message, [ my_apns, ApnsMsg ]);
        _OthersAppkey ->
            util:print("[ maintain_apns send_msg ]: ShowMsg:~ts Count:~p ~n", [ShowMsg, Count]),
            cast_svc:cast(Node, apns, send_message, [ maintain_apns, ApnsMsg ])
    end.

%%%=============================================================================
%%% gen_server callbacks
%%%=============================================================================

init([Id, Apns]) ->
    gproc_pool:connect_worker(?APNS_POOL, {?MODULE, Id}),
    case net_adm:ping(Apns) of
        pang ->
            io:format("connect apn server ~p fail~n", [Apns]);
        pong ->
            io:format("connect apn server ~p succeed~n", [Apns])
    end,
    {ok, #state{id = Id, apn_server = Apns}}.

handle_call(Req, _From, State) ->
    lager:error("unexpected request: ~p", [Req]),
    {reply, {error, badreq}, State}.

handle_cast(_Msg, State) ->
    {noreply, State}.

handle_info(_Info, State) ->
    {noreply, State}.

terminate(_Reason, #state{id = Id}) ->
    gproc_pool:disconnect_worker(?APNS_POOL, {?MODULE, Id}), ok.

code_change(_OldVsn, State, _Extra) ->
    {ok, State}.
